package com.jzlin.funhub.admin.service.system;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzlin.funhub.admin.common.consts.RedisConst;
import com.jzlin.funhub.admin.mapper.SysUserMapper;
import com.jzlin.funhub.admin.model.entity.SysUser;
import com.jzlin.funhub.admin.model.req.*;
import com.jzlin.funhub.admin.model.resp.UserArticleCommentPageResp;
import com.jzlin.funhub.admin.model.resp.UserDetailResp;
import com.jzlin.funhub.admin.model.resp.UserLoginResp;
import com.jzlin.funhub.framework.core.exception.LoginException;
import com.jzlin.funhub.framework.core.exception.RegisterException;
import com.jzlin.funhub.framework.core.http.RestRet;
import com.jzlin.funhub.framework.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author jzlin
 * @since 2025-07-11
 */
@Service
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {

    @Autowired
    private UserFollowService userFollowService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 用户登录
     *
     * @param req
     * @return 成功返回用户信息，否则抛异常
     */
    public UserLoginResp doLogin(UserLoginReq req) {
        //校验图形验证码
        if (!req.getCaptchaCode().equals(redisUtil.get(RedisConst.CACHE_KEY.CAPTCHA + req.getCaptchaKey()))) {
            throw new LoginException("验证码错误!");
        }
        //执行用户名密码登录逻辑
        if (StrUtil.isAllNotBlank(req.getUsername(), req.getPassword())) {
            return loginByUsername(req.getUsername(), req.getPassword());
        } else {
            throw new LoginException("缺少登录信息");
        }
    }

    /**
     * 用户名登录
     *
     * @param username 用户名
     * @param password 密码
     * @return 用户信息
     */
    public UserLoginResp loginByUsername(String username, String password) {
        SysUser sysUser = this.query().eq("username", username).one();
        if (sysUser == null || !BCrypt.checkpw(password, sysUser.getPassword())) {
            throw new LoginException("用户名或密码错误");
        }
        // 执行sa-Token登录逻辑
        StpUtil.login(sysUser.getId());

        return new UserLoginResp(sysUser);
    }

    /**
     * 用户注册
     *
     * @param req
     */
    public void register(UserRegisterReq req) {
        if (StrUtil.isAllNotBlank(req.getUsername(), req.getPassword())) {
            registerByUsername(req.getUsername(), req.getPassword());
        } else {
            throw new LoginException("缺少注册信息");
        }
    }

    /**
     * 用户名密码注册
     *
     * @param username 用户名
     * @param password 密码
     */
    public void registerByUsername(String username, String password) {
        boolean exists = this.query().eq("username", username).exists();
        if (exists) {
            throw new RegisterException("用户名已存在");
        }
        String pwHash = BCrypt.hashpw(password, BCrypt.gensalt());

        SysUser newUser = new SysUser();
        newUser.setUsername(username);
        newUser.setPassword(pwHash);
        this.save(newUser);
    }

    /**
     * 校验是否已登录，是则返回登录信息，否则返回null
     *
     * @return
     */
    public UserLoginResp checkLogin() {
        if (StpUtil.isLogin()) {
            SysUser sysUser = this.getById(StpUtil.getLoginIdAsLong());
            return new UserLoginResp(sysUser);
        } else {
            return null;
        }
    }

    /**
     * 用户明细信息
     *
     * @param userId
     * @return
     */
    public UserDetailResp getDetail(Long userId) {
        SysUser sysUser = this.getById(userId);
        UserDetailResp result = new UserDetailResp(sysUser);
        if (!StpUtil.isLogin() || userId == StpUtil.getLoginIdAsLong()) {
            return result;
        }
        //登录用户是否已关注
        result.setHasFollow(userFollowService.checkUserHasFollow(StpUtil.getLoginIdAsLong(), userId));
        return result;
    }

    /**
     * 分页查询用户的文章评论
     *
     * @return
     */
    public IPage<UserArticleCommentPageResp> queryUserArticleCommentPage(UserArticleCommentPageReq req) {
        IPage<?> page = new Page<>(req.getCurrent(), req.getSize());
        return this.baseMapper.queryArticleCommentByUserId(page, req.getUserId());
    }

    /**
     * 更新用户信息
     */
    public void updateUserInfo(UserInfoUpdateReq req) {
        this.update().eq("id", req.getUserId())
                .set(StrUtil.isNotBlank(req.getAvatar()), "avatar", req.getAvatar())
                .set(StrUtil.isNotBlank(req.getNickname()), "nickname", req.getNickname())
                .set(StrUtil.isNotBlank(req.getCover()), "cover", req.getCover())
                .set("signature", req.getSignature())
                .update();
    }

    /**
     * 被关注
     * @param increase true则+1 false则-1
     */
    public void updateFollowedCount(Long userId, boolean increase) {
        if (increase) {
            this.update().eq("id", userId).setIncrBy("followed_count", 1).update();
        } else {
            this.update().eq("id", userId).setDecrBy("followed_count", 1).update();
        }
    }

    /**
     * 关注
     * @param increase true则+1 false则-1
     */
    public void updateFollowCount(Long userId, boolean increase) {
        if (increase) {
            this.update().eq("id", userId).setIncrBy("follow_count", 1).update();
        } else {
            this.update().eq("id", userId).setDecrBy("follow_count", 1).update();
        }
    }

    /**
     * 文章评论+1
     */
    public void increaseArticleCommentCount(Long userId) {
        this.update().eq("id", userId).setIncrBy("article_comment_count", 1).update();
    }

    /**
     * 文章发表数量
     */
    public void updateArticleCount(Long userId, boolean increase) {
        if (increase) {
            this.update().eq("id", userId).setIncrBy("article_count", 1).update();
        } else {
            this.update().eq("id", userId).setDecrBy("article_count", 1).update();
        }
    }

    /**
     * 修改密码
     * @param req
     */
    public void updatePwd(UserPwdUpdateReq req) {
        SysUser sysUser = this.getById(StpUtil.getLoginIdAsLong());
        if (sysUser == null || !BCrypt.checkpw(req.getOldPwd(), sysUser.getPassword())) {
            throw new LoginException("密码错误");
        }

        String pwHash = BCrypt.hashpw(req.getNewPwd(), BCrypt.gensalt());
        sysUser.setPassword(pwHash);
        updateById(sysUser);
    }
}
